﻿
#region Copyright & License
// --------------------------
// Copyright 2008 Daniel Gray
// --------------------------
// This file is part of Kale.
//
// Kale is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Kale is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with Kale.  If not, see <http://www.gnu.org/licenses/>.
#endregion
#region File details
// --------------------------------------------------------
// Filename          : DiskNodeProvider.cs
// Author            : Daniel Gray
// Created           : 15/04/2008
// --------------------------------------------------------
#endregion
            
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Security;
using Kale.Core.Configuration;

namespace Kale.Core
{
   public class SourceNodeProvider : INodeProvider
   {
      private NodeSource _sourceType;
      private IImageNode _sourceNode;
      private INodeProvider _rootProvider;
      private Dictionary<string, INodeProvider> _storeNodeProviders = new Dictionary<string,INodeProvider>();

      public SourceNodeProvider(NodeSource sourceType, INodeProvider rootProvider, INodeProvider[] storeNodeProviders)
      {
         _sourceType = sourceType;
         _rootProvider = rootProvider;

         foreach (INodeProvider provider in storeNodeProviders)
         {
            _storeNodeProviders.Add(provider.Name, provider);
         }

         _sourceNode = new ImageNode(new NodeId(_sourceType, string.Empty, string.Empty), NodeType.Folder, string.Empty, "Local Photos", this);
      }

      public static SourceNodeProvider CreateDiskSourceNodeProviderFromConfig(INodeProvider rootProvider, DiskStoreElementCollection configurationElements)
      {
         List<INodeProvider> diskStoreProviders = new List<INodeProvider>();

         foreach (DiskStoreElement element in configurationElements)
         {
            diskStoreProviders.Add(new DiskStoreNodeProvider(element.Name, element.PathInfo, rootProvider));
         }

         return new SourceNodeProvider(NodeSource.Disk, rootProvider, diskStoreProviders.ToArray());
      }

      private UnknownStoreException CreateUnknownStoreException(string store)
      {
         return new UnknownStoreException(string.Format("No provider for store '{0}'", store));
      }

      private void AssertSupportedNodeSource(NodeSource source)
      {
         if (source != SupportedNodeSourceType) throw new UnsupportedNodeSourceException(string.Format("This provider does not support the source '{0}'", source));
      }

      private INodeProvider GetStoreNodeProvider(string store)
      {
         if (_storeNodeProviders.ContainsKey(store))
         {
            return _storeNodeProviders[store];
         }
         else
         {
            throw CreateUnknownStoreException(store);
         }
      }

      #region INodeProvider Members

      public void ClearCaches()
      {
         lock (_storeNodeProviders)
         {
            foreach (INodeProvider provider in _storeNodeProviders.Values) provider.ClearCaches();
         }
      }

      public IImageNode LoadParent(NodeId id)
      {
         AssertSupportedNodeSource(id.Source);

         if (id == _sourceNode.NodeId) return _rootProvider.LoadNode(new NodeId(NodeSource.Root, string.Empty, string.Empty));

         return GetStoreNodeProvider(id.Store).LoadParent(id);
      }

      public IImageNode LoadNode(NodeId id)
      {
         AssertSupportedNodeSource(id.Source);

         if (id == _sourceNode.NodeId) return _sourceNode;

         return GetStoreNodeProvider(id.Store).LoadNode(id);
      }

      public IImageNode[] LoadChildren(NodeId id)
      {
         AssertSupportedNodeSource(id.Source);

         if (id == _sourceNode.NodeId)
         {
            List<IImageNode> childNodes = new List<IImageNode>();
            foreach (INodeProvider provider in _storeNodeProviders.Values)
            {
               NodeId childId = new NodeId(_sourceType, provider.Name, string.Empty);
               childNodes.Add(provider.LoadNode(childId));
            }
            return childNodes.ToArray();
         }
         else
         {
            return GetStoreNodeProvider(id.Store).LoadChildren(id);
         }
      }

      public NodeSource SupportedNodeSourceType
      {
         get { return _sourceType; }
      }

      public NodeSource? SupportedParentNodeSourceType
      {
         get { return _sourceType; }
      }

      public string Name
      {
         get { return _sourceType.ToString(); }
      }

      #endregion
   }
}
